iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
1
Modern Web

Fabricjs 筆記系列 第 22 篇

Day 22 - Fabricjs 圖形裁切基礎介紹

  • 分享至 

  • xImage
  •  

裁切功能在一般圖片編輯軟體相當的常見,這邊也能夠透過 Fabricjs 來做圖片裁切的功能,甚至可以做出讓使用者自行決定裁切的位置,切出他們想要留下的範圍,或是用一些特別的圖形來做特別的裁切效果。

Fabricjs 提供的裁切功能,就在最近發布的 2.4.0 版本之後,能夠直接使用 Fabricjs 創建出來的物件和物件重疊,再決定裁切的效果要如何。

而在 2.4.0 版本之前則需要使用物件中的 clipTo 屬性,必須使用原生 canvas 的語法來做裁切的效果。

在 2.4.0 版本之後的這個改動,能夠讓我們更加簡單的去使用 fabricjs 所提供的裁切功能,且不須要太多原生知識就能夠執行了,不過還是保留了 2.4.0 版本之前的 clipTo 提供了更彈性的使用方法。

clipTo 屬性介紹 (2.4.0 版本之前)

這邊先來簡單介紹一下 2.4.0 以前 clipTo 屬性的使用,其實使用方法也很簡單,只要將 clipTo 屬性設定為 callBack function ,並且使用 ctx 來做繪畫,使用 canvas 原生的繪圖方式畫出一個形狀之後,fabricjs render 時就會自動做裁切了。

const imgEl = document.createElement('img')
imgEl.crossOrigin = 'Anonymous'
imgEl.src = 'https://i.imgur.com/1k9XjUn.jpg'
imgEl.onload = () => {
  const image = new fabric.Image(imgEl, {
    scaleX: 0.5,
    scaleY: 0.5,
    angle: 15,
    top: 60,
    left: 300,
    clipTo: function (ctx) {
      ctx.arc(0, 0, 200, 0, Math.PI * 2, true)
    }
  })
  canvas.add(image)
}

clipPath 屬性介紹 (2.4.0 版本之後)

2.4.0 版本後,若要做裁切的功能,可以先新增一個物件暫存起來,再加入到想要裁切的物件中的 clipPath 屬性中。

讓我們來實作這部分。

先設定一個圓形來準備做裁切

這邊因為是要來拿做裁切的物件,所以它的 top left 屬性視參照於被裁切的物件,且被裁切物件起始點為物件的中心。

// 以被裁切物件的中心為起始點
const clipPath = new fabric.Circle({
  radius: 200,
  top: -200, // 被裁切物件中心點為基準的 -200
  left: -200 // 被裁切物件中心點為基準的 -200
})

設定 clipPath

透過設定被裁切物件的 clipPath 屬性,指定為 clipPath 為上面新增的圓形,這樣一來,就能做出裁切的效果,圖片只顯示圓形半徑為 200 的部分,也就是兩個物件所重疊的部分。

imgEl.onload = () => {
  const image = new fabric.Image(imgEl, {
    scaleX: 0.5,
    scaleY: 0.5,
    top: 60,
    left: 300,
    clipPath // 這個 clipPath 為設定裁切的關鍵
  })
  canvas.add(image)
}

結果會同上

使用群組裁切

新的裁切功能,可以更自由的使用裁切,能夠透過群組物件 (group) ,作為裁切或是被裁切的物件。

接下來會來試試使用群組當做裁切遮罩,以及讓群組被裁切。

裁切群組

做出組合當作裁切遮罩

如果你想要把裁切遮罩完美的對齊正中間,請將 originX originY 設定成 'center',且不需要再額外設定 left top

const groupClip = new fabric.Group([
  new fabric.Rect({ width: 50, height: 50 }),
  new fabric.Rect({ width: 50, height: 50, angle: 45 }),
  new fabric.Rect({ width: 50, height: 50, angle: 90 }),
  new fabric.Rect({ width: 50, height: 50, angle: 135 }),
  new fabric.Rect({ width: 50, height: 50, angle: 180 }),
  new fabric.Rect({ width: 50, height: 50, angle: 225 }),
  new fabric.Rect({ width: 50, height: 50, angle: 270 }),
  new fabric.Rect({ width: 50, height: 50, angle: 315 })
], {
  scaleX: 3,
  scaleY: 3,
  originX: 'center',
  originY: 'center'
})

再來一樣設定 clipPath 指定為 groupClip 物件。

  const groupImage = new fabric.Image(imgEl, {
    scaleX: 0.5,
    scaleY: 0.5,
    clipPath: groupClip
  })
  canvas.add(groupImage)

OK 完成

群組切群組

依照上面的邏輯,可以很間單的做出群組切群組的功能,只要好好地將 clipPath 設定好就行了。

const circleClip = new fabric.Group([
  new fabric.Circle({ radius: 50, top: -50, left: -50 }),
  new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black' }),
  new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 90 }),
  new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 180 }),
  new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 270 })
])
const group = new fabric.Group([
    new fabric.Rect({ width: 100, height: 100, fill: 'red' }),
    new fabric.Rect({ width: 100, height: 100, fill: 'yellow', left: 100 }),
    new fabric.Rect({ width: 100, height: 100, fill: 'blue', top: 100 }),
    new fabric.Rect({ width: 100, height: 100, fill: 'green', left: 100, top: 100 })
  ], {
  clipPath: circleClip
})
canvas.add(group)

本日小結

今天介紹了幾種裁切物件的方式,個人覺得在 2.4.0 版本過後 Fabricjs 所提供的 clipPath 實在是相當簡單易用,尤其在群組裁切的部分,不需要自己再去用 canvas 原生 api 刻出複雜的圖形,透過搭配 fabric.Group 功能就可以做到很方便的裁切。

本日 - codepen

參考資料

  • 可參考之前文章

Day 4 -認識各種 Fabricjs 提供的物件型態
Day 13 - 把物件群組起來


上一篇
Day 21 - Fabricjs Zoom in & Zoom out
下一篇
Day 23 - Fabricjs 圖形裁切進階
系列文
Fabricjs 筆記 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言